<script setup lang="ts">
import fileReq from "@/api/file";
import {computed, nextTick, ref, watch} from "vue";
import {useRoute, useRouter} from "vue-router";
import OpenFileDialog from "@/views/dashboard/OpenFileDialog.vue";
import {FileResult} from "@/entityType/FileResult";
import FileTools from "@/views/dashboard/FileTools.vue";
import {imgTypeOptions, zipTypeOptions} from "@/config/options";
import pathBrowserify from "path-browserify";
import CacheImg from "@/components/CacheImg/index.vue";
import {SortObjType} from "@/views/dashboard/type";
import {deepClone} from "@/utils";
import VirtualScroller from "@/components/VirtualScroller/VirtualScroller.vue";
import FlexAuto3 from "@/components/FlexAuto3.vue";

const $useRouter = useRouter()
const $useRoute = useRoute()

let sortObj = ref<SortObjType>({
  up:'递增',
  sort: '名字',
  group: '空',
  filterName: '',
})


let files = ref<FileResult[]>([])


/**
 * 获取到了所有类型
 */
const getFileTypes = computed(()=>{
  let result = [] as string[]
  const filesValue = deepClone(files.value) as FileResult[]
  filesValue.forEach(i=>{
    if(i.directory) {
      if(!result.includes('文件夹')) {
        result.push('文件夹')
      }
    } else {
      let extname = pathBrowserify.extname(i.fileName).substring(1);
      if(!result.includes(extname)) {
        result.push(extname)
      }
    }
  })
  return result
})


const fileTypeWithUp = computed(()=>{
  let result = deepClone(getFileTypes.value)
  if(sortObj.value.up === '递增') {
    result = result.sort((a, b) => {
      return a.localeCompare(b)
    })
  } else {
    result = result.sort((a, b) => {
      return b.localeCompare(a)
    })
  }
  return result
})

/**
 * 根据文件类型获取的文件
 */
const fileTypesFiles = computed(()=>{
  const filesValue = deepClone(files.value) as FileResult[]
  return fileTypeWithUp.value.map(type=>{
    if(type==='文件夹'){
      return filesValue.filter(i=>{
        return i.directory
      })
    } else {
      return filesValue.filter(i=>{
        let extname = pathBrowserify.extname(i.fileName).substring(1);
        if(type === extname) {
          return true
        }
        return false
      })
    }
  })
})

const getFileWithSortObj = computed(() => {
  let result: FileResult[] = []
  let sortObjValue = sortObj.value;
  const filesValue = deepClone(files.value) as FileResult[]
  if (sortObjValue.up === '递增') {
    if (sortObjValue.sort === '名字') {
      if (sortObjValue.group === '空') {
        result = filesValue.sort((a, b) => {
          return a.fileName.localeCompare(b.fileName)
        })
      } else if (sortObjValue.group === '类型') {
        result = fileTypesFiles.value.map(i=>{
          return i.sort((a, b) => {
            return a.fileName.localeCompare(b.fileName)
          })
        }).flat()
      }
    }
  } else {
    if (sortObjValue.sort === '名字') {
      if (sortObjValue.group === '空') {
        result = filesValue.sort((a, b) => {
          return b.fileName.localeCompare(a.fileName)
        })
      } else if (sortObjValue.group === '类型') {
        result = fileTypesFiles.value.map(i=>{
          return i.sort((a, b) => {
            return b.fileName.localeCompare(a.fileName)
          })
        }).flat()
      }
    }
  }
  return result
})

const getFileWithSortObjAndFilter = computed(()=>{
  let result = deepClone(getFileWithSortObj.value)
  let sortObjValue = sortObj.value;
  if (sortObjValue.filterName) {
    result = result.filter(i => {
      if (i.fileName.toLowerCase().includes(sortObjValue.filterName.toLowerCase())) {
        return true
      }
      return false
    })
  }
  // fileListShow.value = false
  // nextTick(()=>{
  //   fileListShow.value = true
  // })
  return result.sort((a, b) => {
    return b.directory - a.directory
  })
})
const OpenFileDialogRef = ref<any>(null)

const paths = computed(() => {
  const paths = ($useRoute.params.pathMatch as string[] || [])
    .filter(i => !!i)
    .map(i => {
      return {
        label: i,
        value: i,
      }
    })
  return [
    {
      label: '根目录',
      value: 'dashboard'
    },
    ...paths,
  ];
})
let selectOne = ref<boolean>(true)
let selectFileName = ref<string[]>([])

function getBasePath() {
  let path = '/'+paths.value.map(i=>{
    return i.value
  }).join('/')
  let basePath = '/'
  if (path !== '/dashboard') {
    basePath = path.replace("/dashboard", "")
  }
  return basePath
}

let fileListShow = ref(true)

function getFileList() {
  RefreshFileList().then(res => {
    nextTick(() => {
      fileListShow.value=true
      OpenFileDialogRef.value.open()
    })
  })
}
function RefreshFileList() {
  let basePath = getBasePath()
  return fileReq.getFileList(basePath).then(res => {
    files.value = (res.data as FileResult[]).map(i=>{
      i.path = pathBrowserify.resolve(basePath,i.fileName)
      return i
    })
  })
}

watch(() => paths.value.length, (value, oldValue, onCleanup) => {
  if (value === oldValue) {
    return
  }
  selectFileName.value = []
  getFileList()
  fileListShow.value=false
}, {immediate: true})

const openFile = computed(() => {
  return ($useRoute.query.open || '') as string
})

watch(() => openFile.value, (value, oldValue, onCleanup) => {
  if (files.value.length > 0) {
    nextTick(() => {
      OpenFileDialogRef.value.open()
    })
  }
  if(!value) {
    nextTick(() => {
      OpenFileDialogRef.value?.close()
    })
  }
}, {immediate: true})

function pathsToPath(index): string {
  const slice = paths.value.slice(0,index+1);
  const s = slice.map(i => i.value).join('/');
  return '/'+s
}

function fileClick(item: FileResult) {
  if (selectOne.value) {
    if (selectFileName.value.includes(item.fileName)) {
      if (item.directory) {
        $useRouter.push({
          path: $useRoute.path + '/' + item.fileName
        })
        selectFileName.value = []
      } else {
        $useRouter.push({
          query: {
            open: item.fileName
          }
        })
      }
    }
    selectFileName.value = [item.fileName]
  } else {
    if (selectFileName.value.includes(item.fileName)) {
      selectFileName.value.splice(selectFileName.value.findIndex(i => i === item.fileName), 1);
    } else {
      selectFileName.value.push(item.fileName)
    }
  }
}

function closed() {
  $useRouter.push({
    query: {}
  })
}


function itemNameType(item:FileResult,types:string[]) {
  let find = types.find(i=>{
    return item.fileName.toLowerCase().endsWith(i)
  })
  if(find) {
    return true
  }
  return false
}

function pluginGetFileIcon(item:FileResult) {
  const filePlugins = window.__pagePlugin__.plugins.filter(i=>{
    return i.type === 'fileIcon'
  })
  for (let filePlugin of filePlugins) {
    let result = filePlugin.handler(window.__pagePlugin__,item)
    if(result) {
      return result
    }
  }
  return null
}

const getOpenFIleList = computed(()=>{
  return getFileWithSortObj.value.filter(i=>!i.directory)
})

function getImageSrc(item: FileResult) {
  return fileReq.getFileUrl(pathBrowserify.resolve(getBasePath(),item.fileName))
}

function getFileIcon(item: FileResult) {
  return fileReq.getFileIconUrl(pathBrowserify.resolve(getBasePath(),item.fileName))
}

let gridItems = ref(5)
function setLineNumber() {
  const values = [
    [1366, 5],
    [1200, 4],
    [768, 3],
    [500, 2],
    [-1, 1],
  ]
  for (let value of values) {
    if (window.innerWidth > value[0]) {
      gridItems.value = value[1]
      break;
    }
  }
}

setLineNumber()
window.addEventListener('resize', setLineNumber)

function funcFinished() {
  selectFileName.value = []
  getFileList()
}
</script>

<template>
  <div class="app-container" @click="selectFileName = []">
    <div class="paths">
      <el-breadcrumb separator="/" :key="$useRoute.path">
        <el-breadcrumb-item
          v-for="(item,index) in paths"
          :key="'paths'+index"
          :to="pathsToPath(index)">
          {{ item.label }}
        </el-breadcrumb-item>
      </el-breadcrumb>
    </div>
    <FlexAuto3>
      <VirtualScroller
        class="fileContentHeight"
        v-if="fileListShow"
        :minSize="213.38"
        :list="getFileWithSortObjAndFilter"
        :gridItems="gridItems"
        :buffer="20*gridItems"
        fixed
        itemKey="path"
        item-class="fileItem"
      >
        <template #default="{ itemData, index }">
          <div class="fileItemCenter"
               :class="{selectFile: selectFileName.includes(itemData.fileName)}"
               @click.stop="fileClick(itemData)"
          >
            <div v-if="itemData.directory === true">
              <el-icon
                class="wenjianjia FilmIcon"
              ><Folder /></el-icon>
            </div>
            <div v-else>
              <el-icon
                class="FilmIcon"
                v-if="itemNameType(itemData,['.txt'])"
              ><Document /></el-icon>
              <el-icon
                v-else-if="itemNameType(itemData,['.mp4','.flv'])"
                class="FilmIcon"
              ><Film /></el-icon>
              <el-icon
                v-else-if="itemNameType(itemData,['.doc','.docx'])"
                class="FilmIcon"
                color="#1d99f3"
              ><Document /></el-icon>
              <el-icon
                v-else-if="itemNameType(itemData,['.pdf'])"
                class="FilmIcon"
                color="#da4453"
              ><Document /></el-icon>
              <el-icon
                v-else-if="itemNameType(itemData,['.xls','.xlsx'])"
                class="FilmIcon"
                color="#2ecc71"
              ><Document /></el-icon>
              <el-icon
                v-else-if="itemNameType(itemData,['.mp3','.m4a'])"
                class="FilmIcon"
              ><Headset /></el-icon>
              <CacheImg
                v-else-if="itemNameType(itemData,imgTypeOptions)"
                class="FilmIcon"
                :src="getImageSrc(itemData)"
                style="object-fit: fill"
              />
              <SvgIcon
                name="zip"
                v-else-if="itemNameType(itemData,zipTypeOptions)"
                class="FilmIcon"
              />
              <SvgIcon
                name="APK"
                v-else-if="itemNameType(itemData,['.apk'])"
                class="FilmIcon"
              />
              <SvgIcon
                name="json"
                v-else-if="itemNameType(itemData,['.json'])"
                class="FilmIcon"
              />
              <SvgIcon
                name="歌词"
                v-else-if="itemNameType(itemData,['.lrc','.ass'])"
                class="FilmIcon"
              />
              <component
                v-else-if="pluginGetFileIcon(itemData)"
                class="FilmIcon"
                :is="pluginGetFileIcon(itemData)"
              ></component>
              <!--       获取系统icon，用于兜底，会很模糊，因为icon很小       -->
              <CacheImg
                v-else
                class="FilmIcon"
                :src="getFileIcon(itemData)"
                style="object-fit: fill"
              />
            </div>
            <div class="fileName">
              <span>0</span>
              <div>
                {{ itemData.fileName }}
              </div>
            </div>
          </div>
        </template>
      </VirtualScroller>
    </FlexAuto3>
    <OpenFileDialog
      :open-file="openFile"
      :file-list="getOpenFIleList"
      :base-file-path="getBasePath()"
      ref="OpenFileDialogRef"
      @closed="closed"
      @refreshFileList="getFileList"
    ></OpenFileDialog>
    <FileTools
      :sort-obj="sortObj"
      :select-file-name="selectFileName"
      @func-finished="funcFinished"
      :base-path="$useRoute.path"
      :get-base-path="getBasePath"
      v-model:select-one="selectOne"
      :files="getFileWithSortObj"
      @RefreshFileList="RefreshFileList"
    ></FileTools>
  </div>
</template>
<style lang="scss" scoped>
@import "./var.scss";
.paths{
  padding-bottom: 10px;
  display: flex;
  align-items: center;
  box-sizing: border-box;
}
.app-container{
  display: flex;
  flex-direction: column;
  padding-bottom: 0;
  padding-top: 10px;
}
.fileContentHeight{
  ::v-deep{
    .vxe-table--render-default .vxe-table--body-wrapper table{
      background-color: unset !important;
    }
  }
  .iconActive{
    color: var(--el-color-primary);
  }
  ::v-deep{
    .fileItem{
      margin-right: 0;
      font-size: 18px;
      cursor: pointer;
      //width: 100%;
      width: calc(calc(100% - calc(4 * 10px)) / 5) !important;
      //遍历数组对象，获取对象里面的值需要用map-get
      $widthCount: (
        (maxWidth: '1366546446464564654654px', minWidth: '1366px', number: 5),
        (maxWidth: '1366px', minWidth: '1200px', number: 4),
        (maxWidth: '1200px', minWidth: '768px',number: 3),
        (maxWidth: '768px', minWidth: '500px',number: 2),
        (maxWidth: '500px', minWidth: '0',number: 1),
      );
      @each $user in $widthCount {
        @media screen and (max-width: #{map-get($user,maxWidth)}) and (min-width: #{map-get($user,minWidth)}){
          width: calc(calc(100% - calc(calc(#{map-get($user,number)} - 1) * 10px)) / #{map-get($user,number)}) !important;
          @if map-get($user,number) > 1 {
            @for $i from 1 through map-get($user,number) - 1 {
              &:nth-of-type(#{map-get($user,number)}n + #{$i}) {
                .fileItemCenter{
                  margin-right: 10px;
                }
              }
            }
          }
        }
      }
      box-sizing: border-box;
      text-align: center;
      display: flex;
      align-items: center;
      .fileItemCenter{
        width: 100%;
        margin-bottom: 10px;
        background-color: rgba(204, 204, 204, 0.41);
        padding: 5px 2px;
      }
      .selectFile{
        background-color: #0080f736;
      }
      .wenjianjia{
        color: var(--el-color-primary);
      }
      .FilmIcon{
        font-size: 168px;
        width: 168px;
        height: 168px;
      }
      .fileName{
        position: relative;
        &>span{
          visibility: hidden;
          pointer-events: none;
        }
        &>div{
          position: absolute;
          top: 0;
          left: 0;
          width: 100%;
          text-align: center;
          word-break: break-all;
          white-space: nowrap;
          overflow: hidden;
          text-overflow: ellipsis;
        }
      }
    }
  }
}
</style>
